package com.strive.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.strive.common.dto.SysMenuDto;
import com.strive.entity.SysMenu;
import com.strive.entity.SysUser;
import com.strive.mapper.SysMenuMapper;
import com.strive.mapper.SysUserMapper;
import com.strive.service.SysMenuService;
import com.strive.service.SysUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author strive.Peng
 * @since 2024-03-14
 */
@Service
public class SysMenuServiceImpl extends ServiceImpl<SysMenuMapper, SysMenu> implements SysMenuService {

    @Autowired
    SysUserService sysUserService;
    @Autowired
    SysUserMapper sysUserMapper;

    @Override
    public List<SysMenuDto> getCurrentUserNav() {

        // 获取当前用户信息 只要是注入到spring的bean 都可以使用security中的方法getPrincipal得到用户信息
        String username = (String) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        SysUser user = sysUserService.getByUsername(username); // 获取当前用户信息

        // 获取用户相关的菜单信息
        List<Long> navMenuIds = sysUserMapper.getNavMenuIds(user.getId());
        // 根据ID获的菜单
        List<SysMenu> sysMenus = this.listByIds(navMenuIds);

        // 转为树状结构
        List<SysMenu> menuTree = buildTreeMenu(sysMenus);

        // 实体转为DTO
        return covert(menuTree);
    }

    /**
     * 返回菜单列表式转换为一个树状结构
     * 在获取菜单列表式调用
     *
     * @return 返回一个转换好的树状结构List
     */
    @Override
    public List<SysMenu> tree() {
        // 获取所有菜单信息 查询的时进行升序排序
        List<SysMenu> menus = this.list(new QueryWrapper<SysMenu>().orderByAsc("orderNum"));
        // 转成树状结构 调用之前的方法
        return buildTreeMenu(menus);
    }

    /**
     * 将menus转换为树状结构
     * 基本原理：遍历所有的菜单表，根据parentID将对应的菜单添加到父级菜单的children中
     *
     * @param sysMenus
     * @return
     */
    private List<SysMenu> buildTreeMenu(List<SysMenu> sysMenus) {
        List<SysMenu> finalMenus = new ArrayList<>();

        /**
         * 基本的层次： 系统管理 - 用户管理 - 添加用户
         * 各自找到各自的孩子
         */
        for (SysMenu menu : sysMenus) {
            for (SysMenu e : sysMenus) {
                // 判断 是否与父级菜单一致 如果一致说明e是menu的孩子
                if (menu.getId() == e.getParentId()) {
                    menu.getChildren().add(e); // 将e 添加到menu的孩子数组中
                }
            }

            /**
             * 提取出父节点
             */
            if (menu.getParentId() == 0L) {
                // 判断是否为顶级菜单 顶级菜单没有父节点 添加
                finalMenus.add(menu);
            }
        }
        return finalMenus;
    }

    /**
     * 将树状结构转换为DTO类
     *
     * @param menuTree
     * @return
     */
    private List<SysMenuDto> covert(List<SysMenu> menuTree) {
        List<SysMenuDto> menuDtos = new ArrayList<>();
        menuTree.forEach(m -> {
            SysMenuDto dto = new SysMenuDto();
            dto.setId(m.getId());
            dto.setName(m.getPerms());
            dto.setTitle(m.getName());
            dto.setComponent(m.getComponent());
            dto.setPath(m.getPath());
            dto.setIcon(m.getIcon());

            // 子节点调用当前方法进行再次转换
            if (m.getChildren().size() > 0) {
                // 递归调用
                dto.setChildren(covert(m.getChildren()));
            }

            menuDtos.add(dto);
        });
        return menuDtos;
    }
}
